docs: add Enterprise Data API reference and usage reports guide#25383
docs: add Enterprise Data API reference and usage reports guide#25383cassio-paesleme wants to merge 10 commits into
Conversation
Add documentation for the Docker Enterprise Data API, which provides programmatic access to organization usage reports (CSV) via api.docker.com/enterprise-data/v1/. - reference/api/enterprise-data/ — OpenAPI 3.0 spec and rendered API reference page for all four endpoints (list types, list reports, download, schema) - manuals/enterprise/reports/ — feature guide with authentication setup (PAT and OAT flows), curl walkthrough, pagination, and troubleshooting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for docsdocker ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🔴 CRITICAL
Two newly added documents (the OpenAPI spec and the feature guide) describe different URL structures for the same API endpoints. One of them is wrong, and users will get 404 errors following whichever document is incorrect.
| - bearerAuth: [] | ||
|
|
||
| paths: | ||
| /orgs/{org_name}: |
There was a problem hiding this comment.
[HIGH] OpenAPI spec paths missing /reports segment — inconsistent with guide
The OpenAPI spec defines the listReportTypes endpoint at /orgs/{org_name} (full URL: https://api.docker.com/enterprise-data/v1/orgs/{org_name}), but the feature guide and the API reference table both consistently use /orgs/{org}/reports as the list-report-types path. The same mismatch applies across all four endpoints:
| OpenAPI spec path | Guide/table path |
|---|---|
GET /orgs/{org_name} |
GET /orgs/{org}/reports |
GET /orgs/{org_name}/{type}/{cadence} |
GET /orgs/{org}/reports/{type}/{cadence} |
GET /orgs/{org_name}/{type}/{cadence}/{date}/download |
GET /orgs/{org}/reports/{type}/{cadence}/{date}/download |
GET /orgs/{org_name}/{type}/{cadence}/{date}/schema |
GET /orgs/{org}/reports/{type}/{cadence}/{date}/schema |
One of these is wrong. If the actual API requires /reports in the path (as the guide shows), users using the spec for client generation or manual calls will get 404 errors. If the spec is correct, every curl example in the guide will fail.
There was a problem hiding this comment.
Fixed in c8fe0a6. Added the missing /reports segment to all four OpenAPI spec paths. They now match the guide.
There was a problem hiding this comment.
Perfect, thank you! Confirmed that all four paths now include /reports and align with the guide. The spec is now consistent and will generate correct client code.
| Discover which report types and cadences are available for your organization. | ||
|
|
||
| ```console | ||
| $ curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports" \ |
There was a problem hiding this comment.
[HIGH] curl examples include /reports path segment not present in OpenAPI spec
All curl examples in this guide include /reports in the path (e.g., /orgs/$ORG/reports, /orgs/$ORG/reports/usage_pulls/daily), but the OpenAPI spec defines paths without this segment (e.g., /orgs/{org_name}, /orgs/{org_name}/{type}/{cadence}).
Both documents are new and were published together, yet they describe different URL structures. Please reconcile: either add the missing /reports segment to all four paths in api.yaml, or remove it from the guide's curl examples and reference table to match the spec.
There was a problem hiding this comment.
Fixed in c8fe0a6. The OpenAPI spec paths now include /reports and match the curl examples.
There was a problem hiding this comment.
Perfect, thank you! I verified the commit and all four paths in the OpenAPI spec now correctly include "/reports" to match the curl examples and documentation. The discrepancy is resolved.
|
|
||
| ```bash | ||
| DATE=$( | ||
| curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily?page_size=1" \ |
There was a problem hiding this comment.
[MEDIUM] Download-latest script silently produces broken output when no reports exist
When the API returns an empty reports list, jq -r '.reports[0].Date' outputs the literal string null (not an empty string). The script then silently:
- Creates a file named
usage_pulls_null.csv - Makes a download request to
.../daily/null/download, which returns a 404
Consider adding a guard to catch this case:
DATE=$(
curl -s "https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily?page_size=1" \
-H "Authorization: Bearer $TOKEN" \
| jq -r '.reports[0].Date // empty'
)
if [ -z "$DATE" ]; then
echo "No reports available."
exit 1
fi
curl -L -o "usage_pulls_${DATE}.csv" \
"https://api.docker.com/enterprise-data/v1/orgs/$ORG/reports/usage_pulls/daily/${DATE}/download" \
-H "Authorization: Bearer $TOKEN"Using // empty makes jq output nothing (empty string) instead of null, so the shell check [ -z "$DATE" ] works correctly for both the no-reports and API-error cases.
There was a problem hiding this comment.
Fixed in e983461. Added // empty to the jq expression and a shell guard that exits early with a message when no reports are available.
There was a problem hiding this comment.
Perfect! Thanks for the quick fix. The guard now correctly handles the empty reports case and prevents the script from creating broken files.
The spec paths were missing the /reports segment, making them inconsistent with the curl examples in the guide and the actual REST handler routes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use jq's // empty alternative operator so an empty report list produces an empty string instead of the literal "null". Add a shell guard to exit early with a message. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure the Enterprise Data API reference to match the sidebar pattern used by Docker Hub API and DVP Data API: - _index.md as hidden section index (build: render: never) - latest.md with layout: api pointing to latest.yaml - changelog.md with initial release entry - deprecated.md with empty deprecation table Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per IAM team guidance, PATs cannot be scoped outside of registry. OATs are the only supported auth mechanism for the Reports API. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| @@ -0,0 +1,238 @@ | |||
| --- | |||
| title: Usage reports | |||
There was a problem hiding this comment.
Usage reports should go under Admin > Organizations, rather than the top level categories. I'll open this up and make some editorial changes.
| - Organization owner role | ||
| - A custom role that includes the **report-read** permission | ||
| - `curl` installed for making API requests | ||
| - `jq` installed for JSON parsing (optional, for formatting responses) |
There was a problem hiding this comment.
| - `jq` installed for JSON parsing (optional, for formatting responses) |
| - One of the following: | ||
| - Organization owner role | ||
| - A custom role that includes the **report-read** permission | ||
| - `curl` installed for making API requests |
There was a problem hiding this comment.
| - `curl` installed for making API requests |
|
|
||
| ## Authentication | ||
|
|
||
| The Reports API requires an Organization Access Token (OAT). OATs are |
There was a problem hiding this comment.
Move into pre-reqs to replace curl/jq prereqs
There was a problem hiding this comment.
Specifically some guidance around having available OATs, since some orgs have limitations; they need an open OAT slot to create a new one (if I'm understanding correctly)
| The Reports API requires an Organization Access Token (OAT). OATs are | ||
| org-scoped tokens designed for machine-to-machine access, making them | ||
| suitable for automated report retrieval workflows. Personal Access Tokens | ||
| (PATs) are not supported. |
There was a problem hiding this comment.
turn into tip call out in prereqs
| - `curl` installed for making API requests | ||
| - `jq` installed for JSON parsing (optional, for formatting responses) | ||
|
|
||
| ## Authentication |
There was a problem hiding this comment.
| ## Authentication | |
| ## Set up OAT for Reports API |
| You use this `TOKEN` value in the `Authorization: Bearer` header for all | ||
| subsequent API calls. | ||
|
|
||
| ## List available report types |
There was a problem hiding this comment.
| ## List available report types | |
| ## List reports |
|
|
||
| ## List available report types | ||
|
|
||
| Discover which report types and cadences are available for your organization. |
There was a problem hiding this comment.
| Discover which report types and cadences are available for your organization. | |
| You can fetch report types and their cadences on a per-organization basis. For example, you can fetch all available reports to your organization, or you can fetch a scoped set of reports by time interval. |
|
|
||
| Discover which report types and cadences are available for your organization. | ||
|
|
||
| ```console |
There was a problem hiding this comment.
| ```console | |
| ### List all available reports | |
| ```console |
| -H "Authorization: Bearer $TOKEN" | jq . | ||
| ``` | ||
|
|
||
| Example response: |
There was a problem hiding this comment.
Per style guide, let's make this a complete sentence. For example:
| Example response: | |
| An example response will describe the report types and cadence. This response tells you that your organization has usage pull reports set to a daily cadence. |
| } | ||
| ``` | ||
|
|
||
| Each entry represents a distinct combination of report type and cadence. Use |
There was a problem hiding this comment.
| Each entry represents a distinct combination of report type and cadence. Use | |
| Each entry represents a distinct combination of report type and cadence. If you have more report types or different cadences configured, you can find that information here. Use |
| Each entry represents a distinct combination of report type and cadence. Use | ||
| these values in subsequent calls. | ||
|
|
||
| ## List reports |
There was a problem hiding this comment.
| ## List reports | |
| ### List reports by type and cadence |
|
|
||
| ## List reports | ||
|
|
||
| List available reports for a given type and cadence. Reports are returned in |
There was a problem hiding this comment.
| List available reports for a given type and cadence. Reports are returned in | |
| Based off the response to the list available reports query, you can list reports by type and cadence. Reports are returned in |
| ## List reports | ||
|
|
||
| List available reports for a given type and cadence. Reports are returned in | ||
| reverse chronological order (most recent first). |
There was a problem hiding this comment.
| reverse chronological order (most recent first). | |
| reverse chronological order so the most recent are listed first. |
| -H "Authorization: Bearer $TOKEN" | jq . | ||
| ``` | ||
|
|
||
| Example response: |
There was a problem hiding this comment.
Add some additional explanation in complete sentence form, per style guide
| -H "Authorization: Bearer $TOKEN" | jq . | ||
| ``` | ||
|
|
||
| ## Download a report |
There was a problem hiding this comment.
| ## Download a report | |
| ## Download reports |
There was a problem hiding this comment.
From a ToC POV, we want these specific actions to be nested and balanced for better visibility. We should add a sentence at minimum that describes why it's best practice to download a report, what you might use it for, and generalized information that's scattered in the below h3s. for example, this would be the place we say reports are downloaded as CSVs.
|
|
||
| ## Download a report | ||
|
|
||
| Download the CSV file for a specific date. The API responds with a `302` |
There was a problem hiding this comment.
| Download the CSV file for a specific date. The API responds with a `302` | |
| ### Download specific reports | |
| Download the CSV file for a specific date. The API responds with a `302` |
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### 401 Unauthorized |
There was a problem hiding this comment.
Super happy you included a troubleshooting section!
akristen
left a comment
There was a problem hiding this comment.
@cassio-paesleme Thanks so much for filing this PR. I've made some comments for myself to act on when I implement a review.
If you could go through and tell me what you think about these suggestions before I start implementing, that would be amazing. :) I will handle all changes on my end since they're mostly editorial in nature and you already did the hard work of generating a draft.
Feel free to ping me on Slack for any questions / and a back and forth, as well as when you'd like this PR out. The main blocker is moving "Usage Reports" under "Admin > Org" so it's on the same level as Activity Logs and Insights. 🫡
The raw OAT cannot be used directly as a Bearer token. It must first be exchanged for a JWT via the Hub auth endpoint. Added the exchange step and a note about JWT expiry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
/reference/api/enterprise-data//manuals/enterprise/reports/Context
Docker Enterprise subscribers will be able to programmatically export organization usage reports (pull data) via
api.docker.com/enterprise-data/v1/. This is a new API surface, separate from the Hub API, supporting both PAT and OAT authentication.Related PRs:
New pages
/reference/api/enterprise-data/api.yaml/reference/api/enterprise-data/index.md/manuals/enterprise/reports/_index.mdTest plan
/reference/api/enterprise-data/🤖 Generated with Claude Code